package cn.net.wanji.service.iml;

import cn.net.wanji.cache.CacheManager;
import cn.net.wanji.cache.IdentifyTypeCacheManager;
import cn.net.wanji.config.ApplicationConfig;

import cn.net.wanji.config.CommonParamConfig;
import cn.net.wanji.entity.*;
import cn.net.wanji.entity.deviceInfo.DeviceInfo;
import cn.net.wanji.entity.deviceStatus.DeviceStatus;
import cn.net.wanji.mapper.*;
import cn.net.wanji.service.DataReceiveService;
import cn.net.wanji.utils.SaveFileUtils;
import cn.net.wanji.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static cn.net.wanji.config.CommonParamConfig.*;
import static cn.net.wanji.job.RefreshGantryDataJob.gantryFlagInfoMap;
import static cn.net.wanji.job.RefreshGantryDataJob.gantryInfoMap;
import static cn.net.wanji.utils.TimeUtils.getDateFormatType;

/**
 * @author guodejun
 * @createTime 2022/10/28 10:20
 * @description
 */
//@Log4j2
@Slf4j(topic = "转换完的数据【DataReceiveServiceImpl】")
@Service
public class DataReceiveServiceImpl implements DataReceiveService {

    @Resource
    DataReceiveMapper dataReceiveMapper;

    @Resource
    ApplicationConfig applicationConfig;

    private final CacheManager cacheManager;

    private final IdentifyTypeCacheManager identifyTypeCacheManager;

    @Autowired
    public DataReceiveServiceImpl(CacheManager cacheManager, IdentifyTypeCacheManager identifyTypeCacheManager) {
        this.cacheManager = cacheManager;
        this.identifyTypeCacheManager = identifyTypeCacheManager;
    }

    @Resource
    SaveFileUtils saveFileUtils;

    public static AtomicInteger datacount = new AtomicInteger(0);

    private KafkaProducer kafkaProducer;

    public static ConcurrentHashMap<String, JSONObject> carLicense = new ConcurrentHashMap<>();

    @Override
    public void dataReceive(JsonRoot jsonRoot) {
        String fileNginx = applicationConfig.getFileNginx(jsonRoot.getRecordId());
        VehicleRsuInfo vehicleRsuInfo = jsonRoot.getVehicleRsuInfo(fileNginx);
        String beforeLicenseCode = vehicleRsuInfo.getLicenseCode();
        String beforeEtcLicense = vehicleRsuInfo.getEtcLicense();
        String recordId = vehicleRsuInfo.getRecordId();
        String erId = vehicleRsuInfo.getErId();
        String detectTime = vehicleRsuInfo.getDetectTime();

        // 首先判断车牌是否为空，是默认车牌
        if (DEFAULT_LICENSE.equals(vehicleRsuInfo.getLicenseCode())) {
            vehicleRsuInfo.setLicenseCode(NULL_LICENSE);
        }
        if (DEFAULT_LICENSE.equals(vehicleRsuInfo.getEtcLicense())) {
            vehicleRsuInfo.setLicenseCode(NULL_LICENSE);
        }
        //判断感知车牌是否成功识别到车牌，如果没有识别成功，使用ETC车牌
        if ((DEFAULT_LICENSE.equals(beforeLicenseCode) || beforeLicenseCode == null) && beforeEtcLicense != null) {
            beforeLicenseCode = beforeEtcLicense;
            vehicleRsuInfo.setLicenseCode(beforeEtcLicense);
        }
        // 根据车牌去查询缓存中是否有对应的carId信息
        if (StringUtils.isEmpty(vehicleRsuInfo.getLicenseCode())) {
            vehicleRsuInfo.setLicenseCode(NULL_LICENSE);
        }
        List<String> carInfoList = new ArrayList<>();
        if (NULL_LICENSE.equals(vehicleRsuInfo.getLicenseCode())) {
            carInfoList = cacheManager.get(DEFAULT_LICENSE, String.class);
        } else {
            carInfoList = cacheManager.get(vehicleRsuInfo.getLicenseCode(), String.class);
        }
        // 判断车牌在缓存中是否存在 如果车牌不存在，则事件根据流水号进行判断
        String licenseCode = vehicleRsuInfo.getLicenseCode();
        Integer vehicleSpeed = vehicleRsuInfo.getVehicleSpeed();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("recordId", recordId);
        if (vehicleSpeed != null) {
            if (StringUtils.isNotNull(licenseCode)) {
                if (NULL_LICENSE.equals(licenseCode)) {
                    if (!carLicense.containsKey(recordId)) {
                        if (vehicleSpeed > Integer.parseInt(applicationConfig.getOverSpeed())) {
                            jsonObject.put("vehicleSpeed", vehicleSpeed);
                            carLicense.put(recordId, jsonObject);
                        } else if (vehicleSpeed < Integer.parseInt(applicationConfig.getLowSpeed())) {
                            jsonObject.put("vehicleSpeed", vehicleSpeed);
                            carLicense.put(recordId, jsonObject);
                        }
                    }
                } else {
                    if (!carLicense.containsKey(licenseCode)) {
                        if (vehicleSpeed > Integer.parseInt(applicationConfig.getOverSpeed())) {
                            jsonObject.put("vehicleSpeed", vehicleSpeed);
                            carLicense.put(licenseCode, jsonObject);
                        } else if (vehicleSpeed < Integer.parseInt(applicationConfig.getLowSpeed())) {
                            jsonObject.put("vehicleSpeed", vehicleSpeed);
                            carLicense.put(licenseCode, jsonObject);
                        }
                    }
                }
            }
        }
        if (carInfoList != null) {
            String newCarId = carInfoList.get(1);
            vehicleRsuInfo.setCarId(newCarId);
        } else {
            if (!StringUtils.isEmpty(vehicleRsuInfo.getLicenseCode())) {
                //重新生成全局唯一carId
                String lic = StringUtils.removeChineseCharacters(vehicleRsuInfo.getLicenseCode());
                String newCarId = erId + "_" + System.currentTimeMillis() + "_" + lic;
                ArrayList<String> arrayList = new ArrayList<>();
                arrayList.add(newCarId);
                arrayList.add(newCarId);
                arrayList.add(detectTime);
                cacheManager.put(vehicleRsuInfo.getLicenseCode(), arrayList,
                        Integer.parseInt(applicationConfig.getPreDataTimeout()));
                vehicleRsuInfo.setCarId(newCarId);
            }
        }
        if (StringUtils.isEmpty(vehicleRsuInfo.getLicenseCode()) && StringUtils.isEmpty(vehicleRsuInfo.getEtcLicense())) {
            String lic = StringUtils.removeChineseCharacters(DEFAULT_LICENSE);
            String newCarId = erId + "_" + System.currentTimeMillis() + "_" + lic;
            ArrayList<String> arrayList = new ArrayList<>();
            arrayList.add(newCarId);
            arrayList.add(newCarId);
            arrayList.add(detectTime);
            cacheManager.put(DEFAULT_LICENSE, arrayList,
                    Integer.parseInt(applicationConfig.getPreDataTimeout()));
            vehicleRsuInfo.setCarId(newCarId);
        }
        // ETC数据没有和Ai感知数据匹配,新增车辆，将ETC的流水号作为全局唯一id
        /*if (vehicleRsuInfo.getCarId() == null || StringUtils.isEmpty(vehicleRsuInfo.getCarId())) {
//            if (DEFAULT_LICENSE.equals(beforeLicenseCode)) {
//                vehicleRsuInfo.setLicenseCode(beforeLicenseCode + Instant.now().getEpochSecond());
//            }
            // 如果车牌已经在carIDToLicense中出现过，则更新全局唯一id
            if (beforeLicenseCode != null && carIDToLicense.containsKey(beforeLicenseCode)) {
                String beforeID = carIDToLicense.get(beforeLicenseCode)[0];
                vehicleRsuInfo.setCarId(beforeID);
                carIDToLicense.put(beforeLicenseCode, new String[]{beforeID, detectTime});
                // 如果车牌没有在carIDToLicense中出现过，新增车辆
            } else {
                if (beforeLicenseCode != null && !DEFAULT_LICENSE.equals(beforeLicenseCode)) {
                    carIDToLicense.put(beforeLicenseCode, new String[]{recordId, detectTime});
                }
                vehicleRsuInfo.setCarId(recordId);
            }
            // 如果匹配成功，则将AI相机carID作为全局唯一id,更新车辆信息
        } else {
            if (!DEFAULT_LICENSE.equals(beforeLicenseCode) && beforeLicenseCode != null && !StringUtils.isEmpty(beforeLicenseCode)) {
                carIDToLicense.put(beforeLicenseCode, new String[]{vehicleRsuInfo.getCarId(), detectTime});
            }
        }
*/
        dataReceiveMapper.insertVehicleRsuInfo(vehicleRsuInfo);
        List<String> licenseList = cacheManager.get(vehicleRsuInfo.getLicenseCode(), String.class);
        if (licenseList != null) {
            vehicleRsuInfo.setCarId(licenseList.get(0));
        } else {
            List<String> licenseList2 = cacheManager.get(DEFAULT_LICENSE, String.class);
            if (licenseList2 != null) {
                vehicleRsuInfo.setCarId(licenseList2.get(0));
            }
        }
        String upGantryId = gantryFlagInfoMap.get("1");
        if (!upGantryId.equals(vehicleRsuInfo.getErId())) {
            vehicleRsuInfo.setIdentifyType(null);
        } else {
            if (vehicleRsuInfo.getIdentifyType() != null) {
                ArrayList<Integer> typeList = new ArrayList<>();
                typeList.add(vehicleRsuInfo.getIdentifyType());
                identifyTypeCacheManager.put(vehicleRsuInfo.getCarId(), typeList,
                        Integer.parseInt(applicationConfig.getPreDataTimeout()) * 4L);
            }
        }
        //log.info("是否需要写入：{},erId:{},vehicleRsuInfo:{}", recordId, erId, vehicleRsuInfo.toString());
        kafkaSend(applicationConfig.getDataTopic(), "", JSON.toJSONString(vehicleRsuInfo));
        //添加上桥门架数据
        if (UPERID.equals(erId)&&!StringUtils.isEmpty(vehicleRsuInfo.getRecordType())&&"B".equals(vehicleRsuInfo.getRecordType())) {
            cacheUpVehicleRsuInfo.add(vehicleRsuInfo);
        }
    }

   /* public static void deleteData() {

        // 获取系统当前时间
        LocalDateTime currentTime = LocalDateTime.now();

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 获取系统当前时间前三小时的时间
        LocalDateTime threeHoursBefore = currentTime.minusHours(1);

        Iterator<Map.Entry<String, String[]>> iterator = DataReceiveServiceImpl.carIDToLicense.entrySet().iterator();

        // 遍历carIDToLicense
        while (iterator.hasNext()) {
            Map.Entry<String, String[]> entry = iterator.next();
            String tr = StringUtils.timeRevise(entry.getValue()[1]);
            // 解析给定时间字符串为LocalDateTime对象
            LocalDateTime dateTimeT1 = LocalDateTime.parse(tr, formatter);
            if (!(dateTimeT1.isAfter(threeHoursBefore) && dateTimeT1.isBefore(currentTime))) {
                iterator.remove();
            }
        }


    }*/

    @Override
    public void saveFile(MultipartFile[] multipartFiles, Integer[] fileTypes, String recordId, String detectTime) {
        // 获取年月日
        LocalDateTime dateTime = LocalDateTime.now();
        String dateFormatType = getDateFormatType(detectTime);
        if (dateFormatType != null) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormatType);
            // 解析时间字符串
            dateTime = LocalDateTime.parse(detectTime, formatter);
        }
        // 获取当前年、月、日
        int year = dateTime.getYear();
        int month = dateTime.getMonthValue();
        int day = dateTime.getDayOfMonth();
        // 格式化月份为两位数显示
        String formattedMonth = String.format("%02d", month);
        // 拼接文件路径
        String fileSavePath = applicationConfig.getFileSavePath() + File.separator + year + formattedMonth
                + File.separator + day + File.separator + recordId + File.separator;
        //判断文件夹是否存在  如果不存在创建对应文件夹
        // 创建File对象
        File folder = new File(fileSavePath);
        if (!folder.exists()) {
            folder.mkdirs();
        }
//        String fileSavePath = applicationConfig.getFileSavePath(recordId) + recordId;
        try {
            List<SaveFailInfo> saveFailInfos = new ArrayList<>();
            for (int i = 0; i < multipartFiles.length; i++) {
                MultipartFile multipartFile = multipartFiles[i];
                Integer fileType = fileTypes[i];
                String fileName = fileSavePath + File.separator + fileType;
                byte[] bytes = multipartFile.getBytes();
                SaveFailInfo saveFailInfo = new SaveFailInfo(bytes, fileType, fileName);
                saveFailInfos.add(saveFailInfo);
            }
            // 开启存储线程，存储文件
            this.saveFileUtils.saveFile(saveFailInfos, fileTypes, fileSavePath, recordId);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 接受设备详情
     *
     * @param deviceInfo
     */
    @Override
    public void deviceInfoData(DeviceInfo deviceInfo) {
        List<MyDeviceInfo> myDeviceInfos = deviceInfo.getMyDeviceInfoList();
        insertOrUpdateMyDeviceInfo(myDeviceInfos);
    }

    private void insertOrUpdateMyDeviceInfo(List<MyDeviceInfo> myDeviceInfos) {
        MyDeviceInfoExample example = new MyDeviceInfoExample();
        myDeviceInfos.forEach(item -> {
            example.clear();
            MyDeviceInfoExample.Criteria criteria = example.createCriteria();
            criteria.andSiteCodeEqualTo(item.getSiteCode());
            criteria.andDeviceCodeEqualTo(item.getDeviceCode());
            criteria.andDeviceTypeCodeEqualTo(item.getDeviceTypeCode());
            long count = myDeviceInfoMapper.countByExample(example);
            // 插入数据
            String obj = JSON.toJSONString(item);
            if (0 == 0) {
                log.info("insert：" + obj);
                myDeviceInfoMapper.insert(item);
            } else {
                log.info("updateByExampleSelective：" + obj);
                myDeviceInfoMapper.updateByExampleSelective(item, example);
            }
        });
    }


    /*  */
    /**
     * 接收设备状态信息
     *
     * @param deviceStatus
     *//*
    @Override
    public void deviceStatusData(DeviceStatus deviceStatus) {
        List<MyDeviceInfo> myDeviceInfos = deviceStatus.getMyDeviceInfoList();
        insertOrUpdateMyDeviceInfo(myDeviceInfos);
    }*/


    @Resource
    MyDeviceInfoMapper myDeviceInfoMapper;


    public static final int[] COLOR_0_4 = {1, 11};
    public static final int[] COLOR_1_5 = {2, 3, 4, 12, 14, 15};
    public static Random random = new Random();


    @Override
    public void preDataReceiveToKafka(PreData preData) {
        String licenseCode = preData.getLicenseCode();
        if (StringUtils.isEmpty(licenseCode)) {
            System.out.println("上桥数据为空");
        }
        String carId = preData.getCarId();
        String erId = preData.getERID();
        String detectTime = preData.getDetectTime();
        // 1、carId 为空
        if (StringUtils.isEmpty(carId)) {
            // 判断车牌是否为空 etc 反馈只有两种 正常和默A0000
            if (!StringUtils.isEmpty(licenseCode)) {
                String lic = StringUtils.removeChineseCharacters(licenseCode);
                // 车牌等于默A00000
                if (!DEFAULT_LICENSE.equals(licenseCode)) {
                    // 拼接唯一carId
                    String newCarId = erId + "_" + System.currentTimeMillis() + "_" + lic;
                    ArrayList<String> arrayList = new ArrayList<>();
                    arrayList.add(newCarId);
                    arrayList.add(newCarId);
                    arrayList.add(detectTime);
                    cacheManager.put(licenseCode, arrayList,
                            Integer.parseInt(applicationConfig.getPreDataTimeout()));
                    preData.setCarId(licenseCode);
                } else {
                    // 获取当前的时间戳
                    String newCarId = erId + "_" + System.currentTimeMillis() + "_" + lic;
                    ArrayList<String> arrayList = new ArrayList<>();
                    arrayList.add(newCarId);
                    arrayList.add(newCarId);
                    arrayList.add(detectTime);
                    cacheManager.put(DEFAULT_LICENSE, arrayList,
                            Integer.parseInt(applicationConfig.getPreDataTimeout()));
                    preData.setCarId(DEFAULT_LICENSE);
                }
            }
            //牌示数据与carId未匹配成功，根据车牌颜色赋值车型
            // 0:蓝色 1：黄色 2：黑色 3：白色 4：渐变绿色 5：黄绿双拼色 6：蓝白渐变色 11：绿色 12：红色
            preData.setVehicleType("1");
            if (preData.getLicenseColor() == 0 || preData.getLicenseColor() == 4) {
                int randomIndex = random.nextInt(COLOR_0_4.length);
                int randomNumber = COLOR_0_4[randomIndex];
                preData.setVehicleType(String.valueOf(randomNumber));
            }
            if (preData.getLicenseColor() == 1 || preData.getLicenseColor() == 5) {
                int randomIndex = random.nextInt(COLOR_1_5.length);
                int randomNumber = COLOR_1_5[randomIndex];
                preData.setVehicleType(String.valueOf(randomNumber));
            }
        } else {
            //2、carId 不为空
            // 判断车牌是否为空
            if (!StringUtils.isEmpty(licenseCode)) {
                String lic = StringUtils.removeChineseCharacters(licenseCode);
                // 车牌等于默A00000
                if (!DEFAULT_LICENSE.equals(licenseCode)) {
                    // 获取当前的时间戳
                    // 拼接唯一carId
                    String newCarId = System.currentTimeMillis() + "_" + lic + "_" + carId;
                    ArrayList<String> arrayList = new ArrayList<>();
                    arrayList.add(carId);
                    arrayList.add(newCarId);
                    arrayList.add(detectTime);
                    cacheManager.put(licenseCode, arrayList,
                            Integer.parseInt(applicationConfig.getPreDataTimeout()));
                } else {
                    //拼接唯一 carId  Todo 针对默A0000的暂不处理
                    String newCarId = System.currentTimeMillis() + "_" + lic + "_" + carId;
                    ArrayList<String> arrayList = new ArrayList<>();
                    arrayList.add(carId);
                    arrayList.add(newCarId);
                    arrayList.add(detectTime);
                    cacheManager.put(licenseCode, arrayList, Integer.parseInt(applicationConfig.getPreDataTimeout()));
                }
            }
        }
//        //如果车牌匹配轨迹数据carid成功，更新车辆信息
//        if (carId != null && !StringUtils.isEmpty(carId)) {
//            // 包含车牌，非默A,将车牌作为全域唯一id
//            if (!DEFAULT_LICENSE.equals(licenseCode) && licenseCode != null && !StringUtils.isEmpty(licenseCode)) {
//                // 发送给仿真，调整车牌号码、车道号、车牌颜色
//                // 将车牌号和carid进行绑定
//                carIDToLicense.put(licenseCode, new String[]{carId, preData.getDetectTime()});
//            }
//            // 未识别车牌，默A,将车牌+秒级时间戳作为作为全域唯一id
//            if (DEFAULT_LICENSE.equals(licenseCode)) {
//                // 发送给仿真，调整车牌号码、车道号、车牌颜色
//                preData.setLicenseCode(licenseCode + Instant.now().getEpochSecond());
//            }
//            //如果车牌匹配轨迹数据carid失败，新增仿真车辆
//        } else {
//
//            /**
//             * 牌示数据与carid未匹配成功，根据车牌颜色赋值车型
//             * 0:蓝色 1：黄色 2：黑色 3：白色 4：渐变绿色 5：黄绿双拼色 6：蓝白渐变色 11：绿色 12：红色
//             */
//            preData.setVehicleType("1");
//            if (preData.getLicenseColor() == 0 || preData.getLicenseColor() == 4) {
//
//                int randomIndex = random.nextInt(COLOR_0_4.length);
//                int randomNumber = COLOR_0_4[randomIndex];
//                preData.setVehicleType(String.valueOf(randomNumber));
//            }
//
//            if (preData.getLicenseColor() == 1 || preData.getLicenseColor() == 5) {
//
//                int randomIndex = random.nextInt(COLOR_1_5.length);
//                int randomNumber = COLOR_1_5[randomIndex];
//                preData.setVehicleType(String.valueOf(randomNumber));
//            }
//
//            // 包含车牌，非默A,将车牌作为全域唯一id
//            if (!DEFAULT_LICENSE.equals(licenseCode) && licenseCode != null && !StringUtils.isEmpty(licenseCode)) {
//                // 将车牌号和carid进行绑定
//                carIDToLicense.put(licenseCode, new String[]{licenseCode, preData.getDetectTime()});
//                preData.setCarId(licenseCode);
//            }
//            // 未识别车牌，默A,将车牌+秒级时间戳作为作为全域唯一id
//            if (DEFAULT_LICENSE.equals(licenseCode)) {
//                //新增仿真车辆
//                preData.setLicenseCode(preData.getLicenseCode() + Instant.now().getEpochSecond());
//                preData.setCarId(licenseCode + Instant.now().getEpochSecond());
//            }
//        }

//        List<String> licenseList = cacheManager.get(licenseCode, String.class);
//        if (licenseList != null) {
//            log.info("牌示数据：{}", licenseList.toString());
//            preData.setCarId(licenseList.get(0));
//        }

        kafkaSend(applicationConfig.getPreDataTopic(), "", JSON.toJSONString(preData));
    }

    @Override
    public void AIDataToKafka(String message) {
//        log.info("kafka发送数据" + message);
        KafkaProducer kafkaProducerInstance = getKafkaProducerInstance();
        kafkaProducerInstance.send(new ProducerRecord(applicationConfig.getAiTopic(), "", message));
    }

    @Override
    public void addAntennaInfo(List<AntennaInfo> antennaInfoList) {
        for (AntennaInfo antennaInfo : antennaInfoList) {
            dataReceiveMapper.addAntennaInfo(antennaInfo);
        }
    }

    @Async
    public void kafkaSend(String topic, String key, String data) {
        KafkaProducer kafkaProducerInstance = getKafkaProducerInstance();
        kafkaProducerInstance.send(new ProducerRecord(topic, key, data));
//        deleteData();
    }

    public KafkaProducer getKafkaProducerInstance() {
        if (null == kafkaProducer) {
            // log.info("创建kafkaProducer");
            Properties props = new Properties();
            props.put("bootstrap.servers", applicationConfig.getKafkaServers());
            props.put("acks", "all");
            props.put("retries", 0);
            props.put("batch.size", 16384);
            props.put("linger.ms", 1);
            props.put("group.id", System.currentTimeMillis());
            props.put("buffer.memory", 33554432);
            props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
            props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
            kafkaProducer = new KafkaProducer(props);
        }
        return kafkaProducer;
    }

}
